package com.campus.food.controller;

import com.campus.food.model.dto.ReplyDto;
import com.campus.food.model.entity.Review;
import com.campus.food.service.ReviewService;
import com.campus.food.util.Result;
import com.campus.food.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

/**
 * 评价控制器
 * 处理评价相关的HTTP请求
 * 
 * @author Claude3.7 Sonnet
 * @since 2025-05-29
 */
@RestController
@RequestMapping("/api/reviews")
@Validated
public class ReviewController {
    
    @Autowired
    private ReviewService reviewService;
    
    /**
     * 添加评价
     * POST /api/reviews
     */
    @PostMapping
    public Result<Review> addReview(@Valid @RequestBody Review review) {
        try {
            Review savedReview = reviewService.addReview(review);
            return Result.success("评价添加成功", savedReview);
        } catch (BusinessException e) {
            return Result.badRequest(e.getMessage());
        } catch (Exception e) {
            return Result.error("添加评价失败，请稍后重试");
        }
    }
    
    /**
     * 根据ID获取评价信息
     * GET /api/reviews/{id}
     */
    @GetMapping("/{id}")
    public Result<Review> getReviewById(@PathVariable @NotNull Long id) {
        try {
            Review review = reviewService.getReviewById(id);
            return Result.success(review);
        } catch (BusinessException e) {
            return Result.notFound(e.getMessage());
        } catch (Exception e) {
            return Result.error("获取评价信息失败");
        }
    }
    
    /**
     * 更新评价信息
     * PUT /api/reviews/{id}
     */
    @PutMapping("/{id}")
    public Result<String> updateReview(@PathVariable @NotNull Long id,
                                     @RequestBody Review review) {
        try {
            review.setId(id);
            boolean success = reviewService.updateReview(review);
            if (success) {
                return Result.success("评价更新成功");
            } else {
                return Result.error("评价更新失败");
            }
        } catch (BusinessException e) {
            return Result.badRequest(e.getMessage());
        } catch (Exception e) {
            return Result.error("更新评价失败");
        }
    }
    
    /**
     * 删除评价
     * DELETE /api/reviews/{id}
     */
    @DeleteMapping("/{id}")
    public Result<String> deleteReview(@PathVariable @NotNull Long id,
                                     @RequestParam @NotNull Long userId) {
        try {
            boolean success = reviewService.deleteReview(id, userId);
            if (success) {
                return Result.success("评价删除成功");
            } else {
                return Result.error("评价删除失败");
            }
        } catch (BusinessException e) {
            return Result.badRequest(e.getMessage());
        } catch (Exception e) {
            return Result.error("删除评价失败");
        }
    }
    
    /**
     * 根据订单ID获取评价
     * GET /api/reviews/order/{orderId}
     */
    @GetMapping("/order/{orderId}")
    public Result<Review> getReviewByOrderId(@PathVariable @NotNull Long orderId) {
        try {
            Review review = reviewService.getReviewByOrderId(orderId);
            if (review == null) {
                return Result.notFound("该订单尚未评价");
            }
            return Result.success(review);
        } catch (BusinessException e) {
            return Result.badRequest(e.getMessage());
        } catch (Exception e) {
            return Result.error("获取评价信息失败");
        }
    }
    
    /**
     * 根据用户ID获取评价列表
     * GET /api/reviews/user/{userId}
     */
    @GetMapping("/user/{userId}")
    public Result<List<Review>> getReviewsByUserId(@PathVariable @NotNull Long userId,
                                                 @RequestParam(defaultValue = "1") int page,
                                                 @RequestParam(defaultValue = "10") int size,
                                                 @RequestParam(required = false) Integer rating) {
        try {
            List<Review> reviews = reviewService.getReviewsByUserId(userId, page, size, rating);
            long total = reviewService.getReviewCountByUserId(userId, rating);
            return Result.success(reviews, total);
        } catch (BusinessException e) {
            return Result.badRequest(e.getMessage());
        } catch (Exception e) {
            return Result.error("获取评价列表失败");
        }
    }
    
    /**
     * 根据商家ID获取评价列表
     * GET /api/reviews/merchant/{merchantId}
     */
    @GetMapping("/merchant/{merchantId}")
    public Result<List<Review>> getReviewsByMerchantId(@PathVariable @NotNull Long merchantId,
                                                     @RequestParam(defaultValue = "1") int page,
                                                     @RequestParam(defaultValue = "10") int size,
                                                     @RequestParam(required = false) Integer rating) {
        try {
            List<Review> reviews = reviewService.getReviewsByMerchantId(merchantId, page, size, rating);
            long total = reviewService.getReviewCountByMerchantId(merchantId, rating);
            return Result.success(reviews, total);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("获取评价列表失败");
        }
    }
    
    /**
     * 商家回复评价
     * POST /api/reviews/{id}/reply
     * @RequestParam @NotNull String reply,
     *                                     @RequestParam @NotNull Long merchantId
     */
    @PostMapping("/{id}/reply")
    public Result<String> replyReview(@PathVariable @NotNull Long id, @RequestBody ReplyDto reply
                                      ) {
        try {
            boolean success = reviewService.replyReview(id, reply.getContent(), reply.getMerchantId());
            if (success) {
                return Result.success("回复成功");
            } else {
                return Result.error("回复失败");
            }
        } catch (BusinessException e) {
            return Result.badRequest(e.getMessage());
        } catch (Exception e) {
            return Result.error("回复评价失败");
        }
    }
    
    /**
     * 获取商家平均评分
     * GET /api/reviews/merchant/{merchantId}/average-rating
     */
    @GetMapping("/merchant/{merchantId}/average-rating")
    public Result<Double> getAverageRatingByMerchantId(@PathVariable @NotNull Long merchantId) {
        try {
            Double averageRating = reviewService.getAverageRatingByMerchantId(merchantId);
            return Result.success(averageRating);
        } catch (BusinessException e) {
            return Result.badRequest(e.getMessage());
        } catch (Exception e) {
            return Result.error("获取平均评分失败");
        }
    }
    
    /**
     * 获取商家评价数量
     * GET /api/reviews/merchant/{merchantId}/count
     */
    @GetMapping("/merchant/{merchantId}/count")
    public Result<Long> getReviewCountByMerchantId(@PathVariable @NotNull Long merchantId,
                                                 @RequestParam(required = false) Integer rating) {
        try {
            long count = reviewService.getReviewCountByMerchantId(merchantId, rating);
            return Result.success(count);
        } catch (BusinessException e) {
            return Result.badRequest(e.getMessage());
        } catch (Exception e) {
            return Result.error("获取评价数量失败");
        }
    }
    
    /**
     * 获取用户评价数量
     * GET /api/reviews/user/{userId}/count
     */
    @GetMapping("/user/{userId}/count")
    public Result<Long> getReviewCountByUserId(@PathVariable @NotNull Long userId,
                                             @RequestParam(required = false) Integer rating) {
        try {
            long count = reviewService.getReviewCountByUserId(userId, rating);
            return Result.success(count);
        } catch (BusinessException e) {
            return Result.badRequest(e.getMessage());
        } catch (Exception e) {
            return Result.error("获取评价数量失败");
        }
    }
    
    /**
     * 检查订单是否已评价
     * GET /api/reviews/order/{orderId}/exists
     */
    @GetMapping("/order/{orderId}/exists")
    public Result<Boolean> checkReviewExists(@PathVariable @NotNull Long orderId) {
        try {
            boolean exists = reviewService.checkReviewExists(orderId);
            return Result.success(exists);
        } catch (BusinessException e) {
            return Result.badRequest(e.getMessage());
        } catch (Exception e) {
            return Result.error("检查失败");
        }
    }
    
    /**
     * 批量删除评价（管理员专用）
     * DELETE /api/reviews/batch
     */
    @DeleteMapping("/batch")
    public Result<String> deleteReviewsBatch(@RequestParam List<Long> ids) {
        try {
            boolean success = reviewService.deleteReviewsBatch(ids);
            if (success) {
                return Result.success("批量删除成功");
            } else {
                return Result.error("批量删除失败");
            }
        } catch (BusinessException e) {
            return Result.badRequest(e.getMessage());
        } catch (Exception e) {
            return Result.error("批量删除评价失败");
        }
    }
    
    /**
     * 获取所有评价列表（管理员专用）
     * GET /api/reviews/admin
     */
    @GetMapping("/admin")
    public Result<List<Review>> getAllReviews(@RequestParam(defaultValue = "1") int page,
                                            @RequestParam(defaultValue = "10") int size,
                                            @RequestParam(required = false) Long userId,
                                            @RequestParam(required = false) Long merchantId,
                                            @RequestParam(required = false) Integer rating) {
        try {
            List<Review> reviews = reviewService.getAllReviews(page, size, userId, merchantId, rating);
            long total = reviewService.getAllReviewCount(userId, merchantId, rating);
            return Result.success(reviews, total);
        } catch (Exception e) {
            return Result.error("获取评价列表失败");
        }
    }
    
    /**
     * 根据评分获取评价列表
     * GET /api/reviews/rating/{rating}
     */
    @GetMapping("/rating/{rating}")
    public Result<List<Review>> getReviewsByRating(@PathVariable @NotNull Integer rating,
                                                 @RequestParam(defaultValue = "1") int page,
                                                 @RequestParam(defaultValue = "10") int size) {
        try {
            List<Review> reviews = reviewService.getReviewsByRating(rating, page, size);
            return Result.success(reviews);
        } catch (Exception e) {
            return Result.error("获取评价列表失败");
        }
    }
    
    /**
     * 获取最新评价列表
     * GET /api/reviews/latest
     */
    @GetMapping("/latest")
    public Result<List<Review>> getLatestReviews(@RequestParam(defaultValue = "10") int limit,
                                               @RequestParam(required = false) Long merchantId) {
        try {
            List<Review> reviews = reviewService.getLatestReviews(limit, merchantId);
            return Result.success(reviews);
        } catch (Exception e) {
            return Result.error("获取最新评价失败");
        }
    }
    
    /**
     * 搜索评价
     * GET /api/reviews/search
     */
    @GetMapping("/search")
    public Result<List<Review>> searchReviews(@RequestParam String keyword,
                                            @RequestParam(defaultValue = "1") int page,
                                            @RequestParam(defaultValue = "10") int size,
                                            @RequestParam(required = false) Long merchantId,
                                            @RequestParam(required = false) Integer rating) {
        try {
            List<Review> reviews = reviewService.searchReviews(keyword, page, size, merchantId, rating);
            return Result.success(reviews);
        } catch (Exception e) {
            return Result.error("搜索评价失败");
        }
    }
    
    /**
     * 获取评价统计信息
     * GET /api/reviews/stats/merchant/{merchantId}
     */
    @GetMapping("/stats/merchant/{merchantId}")
    public Result<Map<String, Object>> getReviewStats(@PathVariable @NotNull Long merchantId) {
        try {
            Map<String, Object> stats = new HashMap<>();
            
            // 总评价数
            long totalReviews = reviewService.getReviewCountByMerchantId(merchantId, null);
            stats.put("totalReviews", totalReviews);
            
            // 平均评分
            Double averageRating = reviewService.getAverageRatingByMerchantId(merchantId);
            stats.put("averageRating", averageRating);
            
            // 各星级评价数量
            stats.put("fiveStarCount", reviewService.getReviewCountByMerchantId(merchantId, 5));
            stats.put("fourStarCount", reviewService.getReviewCountByMerchantId(merchantId, 4));
            stats.put("threeStarCount", reviewService.getReviewCountByMerchantId(merchantId, 3));
            stats.put("twoStarCount", reviewService.getReviewCountByMerchantId(merchantId, 2));
            stats.put("oneStarCount", reviewService.getReviewCountByMerchantId(merchantId, 1));
            
            // 好评率（4星及以上）
            long goodReviews = reviewService.getReviewCountByMerchantId(merchantId, 4) + 
                             reviewService.getReviewCountByMerchantId(merchantId, 5);
            double goodRate = totalReviews > 0 ? (double) goodReviews / totalReviews * 100 : 0;
            stats.put("goodRate", Math.round(goodRate * 100.0) / 100.0);
            
            return Result.success(stats);
        } catch (Exception e) {
            return Result.error("获取评价统计失败");
        }
    }
    
    /**
     * 获取商家评价统计信息
     * GET /api/reviews/statistics/{merchantId}
     */
    @GetMapping("/statistics/{merchantId}")
    public Result<Map<String, Object>> getStatistics(@PathVariable @NotNull Long merchantId) {
        try {
            Map<String, Object> statistics = new HashMap<>();
            
            // 总评价数
            long totalReviews = reviewService.getReviewCountByMerchantId(merchantId, null);
            statistics.put("totalReviews", totalReviews);
            
            // 平均评分
            Double avgRating = reviewService.getAverageRatingByMerchantId(merchantId);
            statistics.put("avgRating", avgRating != null ? avgRating : 0.0);
            
            // 好评率（4星及以上）
            long goodReviews = reviewService.getReviewCountByMerchantId(merchantId, 4) + 
                             reviewService.getReviewCountByMerchantId(merchantId, 5);
            double positiveRate = totalReviews > 0 ? (double) goodReviews / totalReviews : 0;
            statistics.put("positiveRate", positiveRate);
            
            // 回复率
            long repliedReviews = reviewService.getRepliedReviewCount(merchantId);
            double replyRate = totalReviews > 0 ? (double) repliedReviews / totalReviews : 0;
            statistics.put("replyRate", replyRate);
            
            return Result.success(statistics);
        } catch (Exception e) {
            return Result.error("获取评价统计失败");
        }
    }
    
    /**
     * 获取有图评价列表
     * GET /api/reviews/with-images/merchant/{merchantId}
     */
    @GetMapping("/with-images/merchant/{merchantId}")
    public Result<List<Review>> getReviewsWithImages(@PathVariable @NotNull Long merchantId,
                                                   @RequestParam(defaultValue = "1") int page,
                                                   @RequestParam(defaultValue = "10") int size) {
        try {
            List<Review> reviews = reviewService.getReviewsWithImages(merchantId, page, size);
            return Result.success(reviews);
        } catch (Exception e) {
            return Result.error("获取有图评价失败");
        }
    }
    
    /**
     * 获取用户是否可以对订单进行评价
     * GET /api/reviews/can-review/order/{orderId}/user/{userId}
     */
    @GetMapping("/can-review/order/{orderId}/user/{userId}")
    public Result<Boolean> canReviewOrder(@PathVariable @NotNull Long orderId,
                                        @PathVariable @NotNull Long userId) {
        try {
            boolean canReview = reviewService.canReviewOrder(orderId, userId);
            return Result.success(canReview);
        } catch (Exception e) {
            return Result.error("检查失败");
        }
    }
} 